package main

import (
	"fmt"
	"reflect"
)

/*
高阶函数
   可以将一个函数作为另一个函数的参数
func1(),func2()
将func1()函数作为func2()函数的参数
   即func2()函数就叫高阶函数,因为它接受了一个函数作为参数
   则func1()函数就叫回调函数,因为它作为了另一个函数的参数
*/

func func1(a, b int) int {
	fmt.Printf("%p\n", func1)
	return a + b
}

//函数作为参数
func func2(a, b int, fun func(int, int) int) int { //fun为参数名,func(int,int)int 为fun这个参数的返回值
	fmt.Println(a, b, fun) //此处fun指向的是func1函数的地址
	res := fun(a, b)
	return res
}

//函数作为返回值
func fun3() func() int { //fun3函数是一个没有参数且返回值是func() int的函数
	inner := func() int { //fun3函数内有一个匿名没有形参但有int类型返回值的函数 func() int ，且把这个匿名函数赋值给了一个变量inner
		return 1 //变量inner的返回值是1
	}
	fmt.Println(reflect.TypeOf(inner)) //打印变量inner的类型，与匿名函数相同
	return inner                       //fun3函数的返回值  执行fun3函数时
}
func main() {
	fmt.Printf("%T\n", func1)
	fmt.Printf("%T\n", func2)
	res1 := func1(1, 2)
	fmt.Println(res1)
	res2 := func2(10, 20, func1)
	fmt.Println(res2)

	var f func() int
	f = fun3() //f==inner
	res := f() //f()==inner() 相当于执行匿名函数func() int 返回值是1
	fmt.Println(res)
}
